package com.nondo.rdp.stock.endpoint.api;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.nondo.rdp.auth.common.UserUtils;
import com.nondo.rdp.auth.domain.User;
import com.nondo.rdp.auth.endpoint.model.Page;
import com.nondo.rdp.auth.endpoint.model.Query;
import com.nondo.rdp.core.common.CommUtil;
import com.nondo.rdp.core.domain.base.BaseEntity;
import com.nondo.rdp.core.model.View;
import com.nondo.rdp.stock.common.PriceUtils;
import com.nondo.rdp.stock.domain.SimulateAccount;
import com.nondo.rdp.stock.domain.SimulateBuy;
import com.nondo.rdp.stock.domain.SimulateLog;
import com.nondo.rdp.stock.logic.MarketLogic;
import com.nondo.rdp.stock.model.MarketBean;
import com.nondo.rdp.stock.model.SimulateBuyBean;
import com.nondo.rdp.stock.service.SimulateAccountService;
import com.nondo.rdp.stock.service.SimulateBuyService;
import com.nondo.rdp.stock.service.SimulateLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

@RestController("apiStockSimulate")
@RequestMapping("/api/stock/simulate")
public class SimulateEndpoint {
    private final static double INIT_MONEY = 500000;
    @Autowired
    SimulateBuyService simulateBuyService;

    @Autowired
    SimulateLogService simulateLogService;

    @Autowired
    SimulateAccountService simulateAccountService;

    @Autowired
    MarketLogic marketLogic;

    @RequestMapping("index")
    public View openStatus(HttpServletRequest request, HttpServletResponse response, @RequestBody Query<SimulateBuy> query) {
        View view = new View(20000, "获取成功");

        Map returnMap = new HashMap();

        User user = UserUtils.getUser(request, response);

        //判断是否具有开户账户了
        SimulateAccount simulateAccount = this.simulateAccountService.findByUser(user);
        if (simulateAccount == null) {
            simulateAccount = new SimulateAccount();
            simulateAccount.setUser(user);
            simulateAccount.setUsedMoney(INIT_MONEY);
            this.simulateAccountService.save(simulateAccount);

            //设置为第一次进入,弹出页面
            returnMap.put("first", 1);
        } else {
            //设置为非第一次进入
            returnMap.put("first", 0);
        }

        //获取分页的购买记录
        SimulateBuy simulateBuy = query.getData();
        simulateBuy.setUser(user);
        Page<SimulateBuy> page = this.simulateBuyService.findAll(new Page<SimulateBuy>(query.getPage(), query.getSize()), simulateBuy);

        //定义输出数据
        List newAllBuyList = new ArrayList();//输出购买的股票列表
        double todayProfit = 0;//今日收益
        double folatProfit = 0;//持仓浮动盈亏
        double totalMoney = simulateAccount.getUsedMoney();//总资产[公式=可用+当前股票价值]
        double stockMoney = 0;//持仓总价值

        //查询并计算每一股的收益
        query.setPage(0);
        query.setSize(5000);
        Page<SimulateBuy> allBuyList = this.simulateBuyService.findAll(new Page<SimulateBuy>(query.getPage(), query.getSize()), simulateBuy);
        for (SimulateBuy item : allBuyList.getContent()) {
            //①获取可卖数据
            int todayBuy = 0;
            //处理可卖的有多少
            List<SimulateLog> buyLogList = this.simulateLogService.findAllByCodeAndCreateTimeAfter(item.getCode(), CommUtil.getTodayZeroTime());
            for (SimulateLog buyLogItem : buyLogList) {
                todayBuy += buyLogItem.getNum();
            }
            int canSaleNum = item.getLastNum() - todayBuy;//可卖,公式:当前持仓 - 今日购买数量

            //②获取现价
            JSONObject marketBean = marketLogic.getOne(item.getCode());
            JSONArray realArray = marketBean.getJSONArray(item.getCode());
            String nowPriceString = realArray.get(1).toString();//固定第二个参数为当前价格
            double nowPrice = Double.valueOf(nowPriceString).doubleValue();

            String preClosePriceString = realArray.get(7).toString();//固定第七参数为昨日收盘价
            double preClosePrice = Double.valueOf(preClosePriceString).doubleValue();

            //③计算现价的总金额(现价 * 持仓)
            double nowMoney = nowPrice * item.getLastNum();
            //附加计算总价格
            totalMoney += nowMoney;
            //附加计算持仓总价值
            stockMoney += nowMoney;

            //④计算盈亏(现价 - 成本) * 持仓
            double profit = (nowPrice - item.getMoney()) * item.getLastNum();
            //附加计算持仓浮动盈亏
            folatProfit += profit;

            //⑤计算盈亏比例(现价 - 成本) / 成本
            double ratio = (nowPrice - item.getMoney()) / item.getMoney();

            //⑥计算今日收益(现价 - 昨日收盘价) * 持仓
            double oneTodayProfit = (nowPrice - preClosePrice) * item.getLastNum();
            //附加计算今日所有收益
            todayProfit += oneTodayProfit;

            HashMap buyListInfo = new HashMap();
            buyListInfo.put("id", item.getId());
            buyListInfo.put("code", item.getCode());
            buyListInfo.put("name", item.getName());
            buyListInfo.put("nowMoney", PriceUtils.format(nowMoney));//现价总金额
            buyListInfo.put("num", item.getLastNum());//持仓
            buyListInfo.put("canSaleNum", PriceUtils.format(canSaleNum));//可卖
            buyListInfo.put("nowPrice", PriceUtils.format(nowPrice));//现价
            buyListInfo.put("money", PriceUtils.format(item.getMoney()));//成本
            buyListInfo.put("profit", PriceUtils.format(profit));//盈亏金额
            buyListInfo.put("ratio", PriceUtils.format(ratio));//盈亏比例

            newAllBuyList.add(buyListInfo);
        }
        page.setContent(newAllBuyList);
        returnMap.put("page", page);

        //计算今日卖出的总,今日卖出的总金额不能进行取出操作,但是可以进行购买新股票
        double takeOutMoney = 0;//可取金额
        SimulateLog simulateLog = new SimulateLog();
        simulateLog.setUser(user);
        //计算今天开始时间和结束时间
        simulateLog.setCreateTime(CommUtil.getTodayZeroTime());
        simulateLog.setSearchEndTime(CommUtil.getTomorrowdayStartTime());
        Page<SimulateLog> todaySaleList = this.simulateLogService.findAll(new Page<SimulateLog>(0, 5000), simulateLog);
        for (SimulateLog logItem : todaySaleList.getContent()) {
            takeOutMoney += logItem.getTotalMoney();
        }
        if (takeOutMoney >= simulateAccount.getUsedMoney()) {
            takeOutMoney = simulateAccount.getUsedMoney();
        } else {
            takeOutMoney = simulateAccount.getUsedMoney() - takeOutMoney;
        }

        //获取用户的基本账户数据
        returnMap.put("todayProfit", todayProfit);//今日收益
        returnMap.put("folatProfit", folatProfit);//持仓浮动盈亏
        returnMap.put("totalMoney", totalMoney);//总资产
        returnMap.put("totalWorth", stockMoney);//持仓总市值
        returnMap.put("usedMoney", simulateAccount.getUsedMoney());//可用
        returnMap.put("takeOutMoney", takeOutMoney);//可取

        view.setData(returnMap);
        return view;
    }


    @RequestMapping("/list/buy")
    public View<Page> listBuy(HttpServletRequest request, HttpServletResponse response, @RequestBody Query<SimulateBuy> query) {
        View<Page> view = new View(20000, "获取列表成功");

        User user = UserUtils.getUser(request, response);

        SimulateBuy simulateBuy = query.getData();
        simulateBuy.setUser(user);

        Page<SimulateBuy> page = this.simulateBuyService.findAll(new Page<SimulateBuy>(query.getPage(), query.getSize()), simulateBuy);
        List newAllBuyList = new ArrayList();//输出购买的股票列表
        for (SimulateBuy item : page.getContent()) {
            //①获取可卖数据
            int todayBuy = 0;
            //处理可卖的有多少
            List<SimulateLog> buyLogList = this.simulateLogService.findAllByCodeAndCreateTimeAfter(item.getCode(), CommUtil.getTodayZeroTime());
            for (SimulateLog buyLogItem : buyLogList) {
                todayBuy += buyLogItem.getNum();
            }
            int canSaleNum = item.getLastNum() - todayBuy;//可卖,公式:当前持仓 - 今日购买数量

            //②获取现价
            JSONObject marketBean = marketLogic.getOne(item.getCode());
            JSONArray realArray = marketBean.getJSONArray(item.getCode());
            String nowPriceString = realArray.get(1).toString();//固定第二个参数为当前价格
            double nowPrice = Double.valueOf(nowPriceString).doubleValue();

            String preClosePriceString = realArray.get(7).toString();//固定第七参数为昨日收盘价
            double preClosePrice = Double.valueOf(preClosePriceString).doubleValue();

            //③计算现价的总金额(现价 * 持仓)
            double nowMoney = nowPrice * item.getLastNum();

            //④计算盈亏(现价 - 成本) * 持仓
            double profit = (nowPrice - item.getMoney()) * item.getLastNum();

            //⑤计算盈亏比例(现价 - 成本) / 成本
            double ratio = (nowPrice - item.getMoney()) / item.getMoney();

            //⑥计算今日收益(现价 - 昨日收盘价) * 持仓
            double oneTodayProfit = (nowPrice - preClosePrice) * item.getLastNum();

            HashMap buyListInfo = new HashMap();
            buyListInfo.put("id", item.getId());
            buyListInfo.put("code", item.getCode());
            buyListInfo.put("name", item.getName());
            buyListInfo.put("nowMoney", PriceUtils.format(nowMoney));//现价总金额
            buyListInfo.put("num", item.getLastNum());//持仓
            buyListInfo.put("canSaleNum", PriceUtils.format(canSaleNum));//可卖
            buyListInfo.put("nowPrice", PriceUtils.format(nowPrice));//现价
            buyListInfo.put("money", PriceUtils.format(item.getMoney()));//成本
            buyListInfo.put("profit", PriceUtils.format(profit));//盈亏金额
            buyListInfo.put("ratio", PriceUtils.format(ratio));//盈亏比例

            newAllBuyList.add(buyListInfo);
        }
        page.setContent(newAllBuyList);

        view.setData(page);

        return view;
    }

    @RequestMapping("/buy")
    public View buy(HttpServletRequest request, HttpServletResponse response, @Validated @RequestBody SimulateBuyBean simulateBuyBean) {
        View view = new View(20000, "买入股票成功");

        User user = UserUtils.getUser(request, response);

        if (simulateBuyBean.getCode().length() <= 0) {
            return View.ofError("请输入购买的股票代码");
        }

        //判断是否是可交易时间
        Calendar now = Calendar.getInstance();
        int w = now.get(Calendar.DAY_OF_WEEK) - 1;
        int hours = now.get(Calendar.HOUR_OF_DAY);
        int minuts = now.get(Calendar.MINUTE);

        if (w == 0 || w == 6) {
            return View.ofError("非交易时间不能进行交易");
        }

        if ((hours >= 13 && hours <= 15) || (hours == 9 && minuts >= 30) || (hours == 11 && minuts <= 30) || hours == 10) {
            //交易时间可以交易
        } else {
            return View.ofError("非交易时间不能进行交易");
        }

        //获取股票当前信息
        JSONObject marketInfo = marketLogic.getOne(simulateBuyBean.getCode());
        JSONArray realArray = marketInfo.getJSONArray(simulateBuyBean.getCode());
        double currentPrice = Double.valueOf(realArray.get(1).toString()).doubleValue();//当前价格
        String name = realArray.get(0).toString();//股票名字

        double totalMoney = simulateBuyBean.getNum() * currentPrice;

        //判断总金额是否超过了用户的可用模拟金额
        SimulateAccount simulateAccount = this.simulateAccountService.findByUser(user);
        if (simulateAccount.getUsedMoney() < totalMoney) {
            return View.ofError("金额不足");
        }

        //判断股票数量是否符合要求
        if (simulateBuyBean.getNum() % 100 != 0) {
            return View.ofError("购买的股票数量必须是100的倍数");
        }

        //查找是否购买过该股票
        SimulateBuy simulateBuy = this.simulateBuyService.findByCodeAndUser(simulateBuyBean.getCode(), user);
        if (simulateBuy == null) {//没有正在持仓的该股票
            try {
                //变更总金额
                simulateAccount.setUsedMoney(simulateAccount.getUsedMoney() - totalMoney);
                this.simulateAccountService.save(simulateAccount);

                //添加买入的股票
                simulateBuy = new SimulateBuy();
                simulateBuy.setUser(user);
                simulateBuy.setCode(simulateBuyBean.getCode());
                simulateBuy.setName(name);
                simulateBuy.setMoney(currentPrice);
                simulateBuy.setNum(simulateBuyBean.getNum());
                simulateBuy.setLastNum(simulateBuyBean.getNum());
                simulateBuy.setTotalMoney(totalMoney);
                simulateBuy.setCreateTime(new Date());
                this.simulateBuyService.save(simulateBuy);

                //创建买入的股票日志
                SimulateLog simulateLog = new SimulateLog();
                simulateLog.setCode(simulateBuy.getCode());
                simulateLog.setName(name);
                simulateLog.setUser(user);
                simulateLog.setMoney(currentPrice);
                simulateLog.setNum(simulateBuyBean.getNum());
                simulateLog.setTotalMoney(totalMoney);
                simulateLog.setCreateTime(new Date());
                simulateLog.setType(SimulateLog.TYPE_BUY);
                this.simulateLogService.save(simulateLog);
            } catch (Exception e) {
                return View.ofError("买入失败,请稍候重试");
            }
        } else {
            try {
                //变更总金额
                simulateAccount.setUsedMoney(simulateAccount.getUsedMoney() - totalMoney);
                this.simulateAccountService.save(simulateAccount);

                //具有正在持仓的该股票,需要合并数据
                //公式为(Anum * Amoney + Bnum * Bnumber) / (Anum + Bnum)
                double nowMoney = (simulateBuy.getLastNum() * simulateBuy.getMoney() + simulateBuyBean.getNum() * simulateBuyBean.getMoney()) / (simulateBuy.getLastNum() + simulateBuyBean.getNum());
                simulateBuy.setMoney(nowMoney);
                simulateBuy.setNum(simulateBuy.getNum() + simulateBuyBean.getNum());
                simulateBuy.setLastNum(simulateBuy.getLastNum() + simulateBuyBean.getNum());
                simulateBuy.setTotalMoney(simulateBuy.getTotalMoney() + totalMoney);
                this.simulateBuyService.save(simulateBuy);

                //创建买入的股票日志
                SimulateLog simulateLog = new SimulateLog();
                simulateLog.setCode(simulateBuy.getCode());
                simulateLog.setName(name);
                simulateLog.setUser(user);
                simulateLog.setMoney(currentPrice);
                simulateLog.setNum(simulateBuyBean.getNum());
                simulateLog.setTotalMoney(totalMoney);
                simulateLog.setCreateTime(new Date());
                simulateLog.setType(SimulateLog.TYPE_BUY);
                this.simulateLogService.save(simulateLog);
            } catch (Exception e) {
                return View.ofError("买入合并失败,请稍候重试");
            }
        }

        return view;
    }

    @RequestMapping("/sale")
    public View sale(HttpServletRequest request, HttpServletResponse response, @Validated @RequestBody SimulateBuyBean simulateBuyBean) {
        View view = new View(20000, "卖出股票成功");

        User user = UserUtils.getUser(request, response);

        //判断是否是可交易时间
        Calendar now = Calendar.getInstance();
        int w = now.get(Calendar.DAY_OF_WEEK) - 1;
        int hours = now.get(Calendar.HOUR_OF_DAY);
        int minuts = now.get(Calendar.MINUTE);

        if (w == 0 || w == 6) {
            return View.ofError("非交易时间不能进行交易");
        }

        if ((hours >= 13 && hours <= 15) || (hours == 9 && minuts >= 30) || (hours == 11 && minuts <= 30) || hours == 10) {
            //交易时间可以交易
        } else {
            return View.ofError("非交易时间不能进行交易");
        }

        SimulateBuy simulateBuy = this.simulateBuyService.findByCodeAndUser(simulateBuyBean.getCode(), user);

        //计算总的卖出金额
        double totalMoney = simulateBuyBean.getNum() * simulateBuyBean.getMoney();

        //判断股票是否为当日购买,当日购买的股票次日才能购买
        if (CommUtil.dateFormat(simulateBuy.getCreateTime(), "yyyy-MM-dd").equals(CommUtil.dateFormat(new Date(), "yyyy-MM-dd"))) {
            return View.ofError("当日购买的股票次日才能卖出");
        }

        if (simulateBuy.getLastNum() <= 0) {
            return View.ofError("该股票已卖完");
        }

        //校验非法数据
        if (simulateBuy.getNum() < 100) {
            return View.ofError("卖出的股票数量不能低于1");
        }

        //判断股票数量是否符合要求
        if (simulateBuy.getNum() % 100 != 0) {
            return View.ofError("卖出的股票数量必须是100的倍数");
        }

        //判断最大可以卖出多少股票
        if (simulateBuyBean.getNum() > simulateBuy.getLastNum()) {
            return View.ofError("卖出的股票数量超过了最大可卖出的数量");
        }

        try {
            if (simulateBuyBean.getNum() == simulateBuy.getLastNum()) {//全部卖出
                simulateBuy.setLastNum(0);
                simulateBuy.setDelFlag(BaseEntity.DEL_FLAG_DELETE);
            } else {//部分卖出
                simulateBuy.setLastNum(simulateBuy.getLastNum() - simulateBuyBean.getNum());
            }
            this.simulateBuyService.save(simulateBuy);

            //创建卖出股票日志
            SimulateLog simulateLog = new SimulateLog();
            simulateLog.setCode(simulateBuy.getCode());
            simulateLog.setName(simulateBuy.getName());
            simulateLog.setUser(user);
            simulateLog.setMoney(simulateBuyBean.getMoney());
            simulateLog.setNum(simulateBuyBean.getNum());
            simulateLog.setTotalMoney(totalMoney);
            simulateLog.setCreateTime(new Date());
            simulateLog.setType(SimulateLog.TYPE_SALE);
            this.simulateLogService.save(simulateLog);

            //变更总资产
            SimulateAccount simulateAccount = this.simulateAccountService.findByUser(user);
            simulateAccount.setUsedMoney(simulateAccount.getUsedMoney() + totalMoney);
            this.simulateAccountService.save(simulateAccount);
        } catch (Exception e) {
            return View.ofError("操作失败,请稍候重试");
        }

        return view;
    }

    @RequestMapping("/log/list/today")
    public View logListToday(HttpServletRequest request, HttpServletResponse response, @RequestBody Query<SimulateLog> query) {
        View view = new View(20000, "获取数据成功");

        User user = UserUtils.getUser(request, response);

        SimulateLog simulateLog = query.getData();
        simulateLog.setUser(user);

        //计算今天开始时间和结束时间
        simulateLog.setCreateTime(CommUtil.getTodayZeroTime());
        simulateLog.setSearchEndTime(CommUtil.getTomorrowdayStartTime());

        Page<SimulateLog> page = this.simulateLogService.findAll(new Page<SimulateLog>(query.getPage(), query.getSize()), simulateLog);

        //处理时间
        for (SimulateLog item : page.getContent()) {
            item.setShowTime(CommUtil.dateFormat(item.getCreateDate(), "HH:mm:ss"));
        }

        view.setData(page);
        return view;
    }

    @RequestMapping("/log/list")
    public View logList(HttpServletRequest request, HttpServletResponse response, @RequestBody Query<SimulateLog> query) {
        View view = new View(20000, "获取数据成功");

        User user = UserUtils.getUser(request, response);

        SimulateLog simulateLog = query.getData();

        //处理时间
        Calendar c = Calendar.getInstance();
        c.setTime(simulateLog.getSearchEndTime());
        c.add(Calendar.DAY_OF_MONTH, 1);// 今天+1天
        Date tomorrow = c.getTime();
        simulateLog.setSearchEndTime(tomorrow);

        simulateLog.setUser(user);
        Page<SimulateLog> page = this.simulateLogService.findAll(new Page<SimulateLog>(query.getPage(), query.getSize()), simulateLog);

        //处理时间
        for (SimulateLog item : page.getContent()) {
            item.setShowTime(CommUtil.dateFormat(item.getCreateDate(), "Y-M-d"));
        }

        view.setData(page);
        return view;
    }

    @RequestMapping("/getOne")
    public View getOne(HttpServletRequest request, HttpServletResponse response, @RequestBody MarketBean marketBean) {
        View view = new View(20000, "获取数据成功");

        User user = UserUtils.getUser(request, response);

        //获取用户资金信息
        SimulateAccount simulateAccount = this.simulateAccountService.findByUser(user);

        //获取股票当前信息
        JSONObject marketInfo = marketLogic.getOne(marketBean.getCode());
        JSONArray realArray = marketInfo.getJSONArray(marketBean.getCode());

        double open = Double.valueOf(realArray.get(6).toString()).doubleValue();//开盘价
        double currentPrice = Double.valueOf(realArray.get(1).toString()).doubleValue();//当前价格

        //计算涨停 公式=开盘价 * 1.1
        double priceCeiling = open * 1.1;

        //计算涨跌 公式=开盘价 * 0.9
        double priceFloor = open * 0.9;

        //计算涨幅 公式=(当前价格 - 开盘价) / 开盘价
        double doup = (currentPrice - open) / open;

        //可卖可买
        int allWarehouse = 0;
        int twoWarehouse = 0;
        int fourWarehouse = 0;
        if (marketBean.getType() == 0) {//买
            allWarehouse = ((int) (simulateAccount.getUsedMoney() / currentPrice) / 100) * 100;
            twoWarehouse = ((int) ((simulateAccount.getUsedMoney() / 2) / currentPrice) / 100) * 100;
            fourWarehouse = ((int) ((simulateAccount.getUsedMoney() / 4) / currentPrice) / 100) * 100;
        } else if (marketBean.getType() == 1) {//卖
            SimulateBuy simulateBuy = this.simulateBuyService.findByCodeAndUser(marketBean.getCode(), user);
            if (simulateBuy != null) {
                allWarehouse = simulateBuy.getLastNum();
                twoWarehouse = ((int) (simulateBuy.getLastNum() / 200)) * 100;
                fourWarehouse = ((int) (simulateBuy.getLastNum() / 400)) * 100;
            } else {
                allWarehouse = 0;
                twoWarehouse = 0;
                fourWarehouse = 0;
            }
        }

        Map returnMap = new HashMap();
        returnMap.put("code", marketBean.getCode());//股票代码
        returnMap.put("name", realArray.get(0));//股票名字
        returnMap.put("priceCeiling", PriceUtils.format(priceCeiling));//涨停
        returnMap.put("priceFloor", PriceUtils.format(priceFloor));//涨跌
        returnMap.put("doup", PriceUtils.format(doup, 4) * 100);//当前涨幅
        returnMap.put("currentPrice", currentPrice);//当前价格
        returnMap.put("usedMoney", simulateAccount.getUsedMoney());//用户账户资金
        returnMap.put("allWarehouse", allWarehouse);//全仓可买
        returnMap.put("twoWarehouse", twoWarehouse);//1/2仓可买
        returnMap.put("fourWarehouse", fourWarehouse);//1/4仓可买

        view.setData(returnMap);

        return view;
    }
}